/*******************************************************************************
 * Copyright (c) 2008 Sylvain Sicard.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Sylvain Sicard - initial API and implementation
 ******************************************************************************/
package fr.jade.fraclite.orb.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.Map;

import org.objectweb.naming.Binder;
import org.objectweb.naming.Name;


/**
 * An {@link ObjectInputStream} that replaces {@link RMIRef} objects with stubs.
 */

public class RmiObjectInputStream extends ObjectInputStream {

  /**
   * The naming context used to decode the identifiers contained in {@link RMIRef}
   * objects.
   */

  protected Binder binder;


  
  /**
   * Constructs a new {@link RmiObjectInputStream}.
   *
   * @param is the underlying input stream.
   * @param binder the naming context to be used to decode the identifiers
   *      contained in {@link RMIRef} objects.
   * @param contextFactory the context factory to be used to create hints for
   *      the {@link Identifier#bind bind} method.
   * @throws IOException if the super constructor throws an exception.
   */
  
  public RmiObjectInputStream (final InputStream is, final Binder binder) throws IOException {
    super(is);
    enableResolveObject(true);
    this.binder = binder;
  }

  /**
   * Replaces {@link RMIRef} objects with corresponding stubs. This method uses
   * the {@link #binder binder} to decode the identifier encoded in a {@link
   * RMIRef} object, and then uses the {@link Identifier#bind bind} method of the
   * decoded identifier to get a stub corresponding to this identifier. The
   * type stored in the {@link RMIRef} object is passed as an hint to the
   * {@link Identifier#bind bind} method.
   *
   * @param obj an object.
   * @return a stub if obj is a {@link RMIRef} object, or <tt>obj</tt>
   *      otherwise.
   * @throws IOException if a {@link RMIRef} object cannot be replaced with a
   *      stub.
   */

  protected Object resolveObject (final Object obj) throws IOException {
    if (obj instanceof Ref) {
      try {        
        Ref ref = (Ref)obj;
        //System.out.println("[RmiObjectInputStream] "+new String(ref.name));
        Name name = binder.decode(ref.name);
        return binder.bind(name, null);
      } catch (Exception e) {
        throw new IOException("cannot bind to object: " + e);
      }
    } else {
      return obj;
    }
  }

}
